import React, { useContext, useMemo, useState } from "react";
import { useQuery } from "@tanstack/react-query";
import aws from "legacy/assets/aws.png";
import cloudformationStatus from "legacy/assets/cloud-formation-stack-complete.png";
import api from "legacy/shared/api";
import theme from "legacy/shared/themes/midnight";
import styled from "styled-components";
import { v4 as uuidv4 } from "uuid";

import { Context } from "shared/Context";

import Button from "./porter/Button";
import Container from "./porter/Container";
import Input from "./porter/Input";
import Link from "./porter/Link";
import Modal from "./porter/Modal";
import Spacer from "./porter/Spacer";
import Step from "./porter/Step";
import Text from "./porter/Text";
import VerticalSteps from "./porter/VerticalSteps";
import PreflightChecks from "./PreflightChecks";

type Props = {
  goBack: () => void;
  proceed: (id: string) => void;
  switchToCredentialFlow: () => void;
};

const CloudFormationForm: React.FC<Props> = ({
  goBack,
  proceed,
  switchToCredentialFlow,
}) => {
  const [AWSAccountID, setAWSAccountID] = useState("");
  const [currentStep, setCurrentStep] = useState<number>(0);
  const [hasClickedCloudformationButton, setHasClickedCloudformationButton] =
    useState(false);
  const [showNeedHelpModal, setShowNeedHelpModal] = useState(false);
  const [preflightData, setPreflightData] = useState<any>(undefined);

  const { currentProject, user } = useContext(Context);
  const markStepStarted = async ({
    step,
    account_id = "",
    cloudformation_url = "",
    error_message = "",
    login_url = "",
    external_id = "",
  }: {
    step: string;
    account_id?: string;
    cloudformation_url?: string;
    error_message?: string;
    login_url?: string;
    external_id?: string;
  }) => {
    try {
      if (currentProject == null) {
        return;
      }
      await api.updateOnboardingStep(
        "<token>",
        {
          step,
          account_id,
          cloudformation_url,
          error_message,
          login_url,
          external_id,
        },
        {
          project_id: currentProject.id,
        }
      );
    } catch (err) {
      // console.log(err);
    }
  };

  const checkCloudFormation = async () => {
    try {
      if (currentProject == null) {
        return false;
      }
      const externalId = getExternalId();
      const targetARN = `arn:aws:iam::${AWSAccountID}:role/porter-manager`;
      await api.createAWSIntegration(
        "<token>",
        {
          aws_target_arn: targetARN,
          aws_external_id: externalId,
        },
        {
          id: currentProject.id,
        }
      );
      setPreflightData({
        Msg: {
          preflight_checks: {
            cloudFormation: {},
          },
        },
      });
      console.log("true");

      return true;
    } catch (err) {
      console.log("false");
      return false;
    }
  };

  const { data: canProceed } = useQuery(
    [
      "createAWSIntegration",
      currentStep,
      hasClickedCloudformationButton,
      AWSAccountID,
    ],
    async () => {
      if (currentProject == null) {
        return false;
      }
      const externalId = getExternalId();
      const targetARN = `arn:aws:iam::${AWSAccountID}:role/porter-manager`;
      await api.createAWSIntegration(
        "<token>",
        {
          aws_target_arn: targetARN,
          aws_external_id: externalId,
        },
        {
          id: currentProject.id,
        }
      );
      setPreflightData({
        Msg: {
          preflight_checks: {
            cloudFormation: {},
          },
        },
      });
      return true;
    },
    {
      enabled: currentStep === 3,
      retry: (failureCount, err) => {
        // if they've waited over 35 seconds notify us on slack. Cloudformation stack should only take around 20-25 seconds to create
        if (failureCount === 7 && hasClickedCloudformationButton) {
          reportFailedCreateAWSIntegration();
        }
        return true;
      },
      retryDelay: 5000,
    }
  );

  const awsAccountIdInputError = useMemo(() => {
    const regex = /^\d{12}$/;
    if (AWSAccountID.trim().length === 0) {
      return undefined;
    } else if (!regex.test(AWSAccountID)) {
      return "A valid AWS Account ID must be a 12-digit number.";
    }
    return undefined;
  }, [AWSAccountID]);

  const handleAWSAccountIDChange = (accountId: string) => {
    setAWSAccountID(accountId);
    setPreflightData(undefined);
    setHasClickedCloudformationButton(false);
    if (accountId === "open-sesame") {
      switchToCredentialFlow();
    }
  };

  const handleContinueWithAWSAccountId = async () => {
    const cloudFormationCheck = await checkCloudFormation();
    cloudFormationCheck ? setCurrentStep(3) : setCurrentStep(2);
    markStepStarted({
      step: "aws-account-id-complete",
      account_id: AWSAccountID,
    });
  };

  const handleProceedToProvisionStep = () => {
    try {
      if (currentProject != null) {
        api.inviteAdmin("<token>", {}, { project_id: currentProject.id });
      }
    } catch (err) {
      console.log(err);
    }
    markStepStarted({
      step: "aws-create-integration-success",
      account_id: AWSAccountID,
    });
    proceed(`arn:aws:iam::${AWSAccountID}:role/porter-manager`);

    try {
      window.dataLayer?.push({
        event: "provision-attempt",
        data: {
          cloud: "aws",
          email: user?.email,
        },
      });
    } catch (err) {
      console.log(err);
    }
  };

  const reportFailedCreateAWSIntegration = () => {
    markStepStarted({
      step: "aws-create-integration-failed",
      account_id: AWSAccountID,
      external_id: getExternalId(),
    });
  };

  const getExternalId = () => {
    let externalId = localStorage.getItem(AWSAccountID);
    if (!externalId) {
      externalId = uuidv4();
      localStorage.setItem(AWSAccountID, externalId);
    }

    return externalId;
  };

  const directToAWSLogin = () => {
    const login_url = `https://signin.aws.amazon.com/console`;
    markStepStarted({ step: "aws-login-redirect-success", login_url });
    window.open(login_url, "_blank");
  };

  const directToCloudFormation = () => {
    setCurrentStep(3);
    const externalId = getExternalId();
    const trustArn = import.meta.env.TRUST_ARN
      ? import.meta.env.TRUST_ARN
      : "arn:aws:iam::108458755588:role/CAPIManagement";
    let cloudformation_url = `https://console.aws.amazon.com/cloudformation/home?#/stacks/create/review?templateURL=https://porter-role.s3.us-east-2.amazonaws.com/cloudformation-policy.json&stackName=PorterRole&param_ExternalIdParameter=${externalId}&param_TrustArnParameter=${trustArn}`;
    if (currentProject.aws_ack_auth_enabled) {
      cloudformation_url = `https://console.aws.amazon.com/cloudformation/home?#/stacks/create/review?templateURL=https://porter-role.s3.us-east-2.amazonaws.com/cloudformation-access-policy.json&stackName=PorterRole&param_TrustArnParameter=${trustArn}`;
    }
    markStepStarted({
      step: "aws-cloudformation-redirect-success",
      account_id: AWSAccountID,
      cloudformation_url,
      external_id: externalId,
    });
    window.open(cloudformation_url, "_blank");
    setHasClickedCloudformationButton(true);
  };

  const renderContent = () => {
    return (
      <>
        <Text>
          Grant Porter permissions to create infrastructure in your AWS account
          by following 3 simple steps.
        </Text>
        <Spacer y={1} />
        <VerticalSteps
          onlyShowCurrentStep={true}
          currentStep={currentStep}
          steps={[
            <>
              <Text size={16}>Log in to your AWS account</Text>
              <Spacer y={0.5} />
              <Text color="helper">
                Return to Porter after successful login.
              </Text>
              <Spacer y={0.5} />
              <AWSButtonContainer>
                <ButtonImg src={aws} />
                <Button
                  width={"170px"}
                  onClick={directToAWSLogin}
                  color="linear-gradient(180deg, #26292e, #24272c)"
                  withBorder
                >
                  Log in
                </Button>
              </AWSButtonContainer>
              <Spacer y={1} />
              <Button
                onClick={() => {
                  setCurrentStep(1);
                }}
              >
                Continue
              </Button>
            </>,
            <>
              <Text size={16}>Enter your AWS account ID</Text>
              <Spacer y={0.5} />
              <Text color="helper">
                Make sure this is the ID of the account you are currently logged
                into and would like to provision resources in.
              </Text>
              <Spacer y={0.5} />
              <Input
                label={
                  <Flex>
                    👤 AWS account ID
                    <i
                      className="material-icons"
                      onClick={() => {
                        window.open(
                          "https://us-east-1.console.aws.amazon.com/billing/home?region=us-east-1#/account",
                          "_blank"
                        );
                      }}
                    >
                      help_outline
                    </i>
                  </Flex>
                }
                value={AWSAccountID}
                setValue={handleAWSAccountIDChange}
                placeholder="ex: 915037676314"
                error={awsAccountIdInputError}
              />
              <Spacer y={1} />
              <StepChangeButtonsContainer>
                <Button
                  onClick={handleContinueWithAWSAccountId}
                  disabled={
                    awsAccountIdInputError != null || AWSAccountID.length === 0
                  }
                >
                  Continue
                </Button>
                <Spacer inline x={0.5} />
                <Button
                  onClick={() => {
                    setCurrentStep(0);
                  }}
                  color="#222222"
                >
                  Back
                </Button>
              </StepChangeButtonsContainer>
            </>,
            <>
              <Text size={16}>Create an AWS CloudFormation stack</Text>
              <Spacer y={0.5} />
              <Text color="helper">
                This grants Porter permissions to create infrastructure in your
                account.
              </Text>
              <Spacer y={0.5} />
              <Text color="helper">
                Clicking the button below will take you to the AWS
                CloudFormation console. Return to Porter after clicking 'Create
                stack' in the bottom right corner.
              </Text>
              <Spacer y={0.5} />
              <AWSButtonContainer>
                <ButtonImg src={aws} />
                <Button
                  width={"170px"}
                  onClick={directToCloudFormation}
                  color="linear-gradient(180deg, #26292e, #24272c)"
                  withBorder
                  disabled={canProceed || preflightData}
                  disabledTooltipMessage={
                    "Porter can already access your account!"
                  }
                >
                  Grant permissions
                </Button>
              </AWSButtonContainer>
              <Spacer y={1} />
              <StepChangeButtonsContainer>
                <Button
                  onClick={() => {
                    setCurrentStep(3);
                  }}
                >
                  Continue
                </Button>
                <Spacer inline x={0.5} />
                <Button
                  onClick={() => {
                    setCurrentStep(1);
                  }}
                  color="#222222"
                  // status={canProceed ? "success" : hasClickedCloudformationButton ? "loading" : undefined}
                  loadingText={`Checking if Porter can access AWS account ID ${AWSAccountID}...`}
                  successText={`Porter can access AWS account ID ${AWSAccountID}`}
                >
                  Back
                </Button>
              </StepChangeButtonsContainer>
            </>,
            <>
              <Text size={16}>Check permissions</Text>
              <Spacer y={0.5} />
              <Text color="helper">
                Checking if Porter can access AWS account with ID {AWSAccountID}
                . This can take up to a minute.
                <Spacer inline width="10px" />
                <Link
                  hasunderline
                  onClick={() => {
                    setShowNeedHelpModal(true);
                  }}
                >
                  Need help?
                </Link>
              </Text>
              <Spacer y={1} />
              <PreflightChecks
                preflightData={preflightData}
                provider={"DEFAULT"}
              />
              <Spacer y={1} />
              <Container row>
                <Button
                  onClick={handleProceedToProvisionStep}
                  disabled={!canProceed}
                >
                  Continue
                </Button>
                <Spacer inline x={0.5} />
                <Button
                  onClick={() => {
                    setCurrentStep(2);
                  }}
                  color="#222222"
                >
                  Back
                </Button>
              </Container>
            </>,
          ]}
        />
        {showNeedHelpModal && (
          <Modal
            closeModal={() => {
              setShowNeedHelpModal(false);
            }}
            width={"800px"}
          >
            <Text size={16}>Granting Porter access to AWS</Text>
            <Spacer y={1} />
            <Text color="helper">
              Porter needs access to your AWS account in order to create
              infrastructure. You can grant Porter access to AWS by following
              these steps:
            </Text>
            <Spacer y={1} />
            <Step number={1}>
              <Link
                to="https://aws.amazon.com/resources/create-account/"
                target="_blank"
              >
                Create an AWS account
              </Link>
              <Spacer inline width="5px" />
              if you don't already have one.
            </Step>
            <Spacer y={1} />
            <Step number={2}>
              Once you are logged in to your AWS account,
              <Spacer inline width="5px" />
              <Link
                to="https://console.aws.amazon.com/billing/home?region=us-east-1#/account"
                target="_blank"
              >
                copy your account ID
              </Link>
              .
            </Step>
            <Spacer y={1} />
            <Step number={3}>
              Fill in your account ID on Porter and select "Grant permissions".
            </Step>
            <Spacer y={1} />
            <Step number={4}>
              After being redirected to AWS CloudFormation, select "Create
              stack" on the bottom right.
            </Step>
            <Spacer y={1} />
            <Step number={5}>
              The stack will start to create. Refresh until the stack status has
              changed from "CREATE_IN_PROGRESS" to "CREATE_COMPLETE":
            </Step>
            <Spacer y={1} />
            <ImageDiv>
              <img src={cloudformationStatus} height="250px" />
            </ImageDiv>
            <Spacer y={1} />
            <Step number={6}>Return to Porter and select "Continue".</Step>
            <Spacer y={1} />
            <Step number={7}>
              If you continue to see issues,{" "}
              <a href="mailto:support@porter.run">email support.</a>
            </Step>
          </Modal>
        )}
      </>
    );
  };

  return (
    <>
      <Container row>
        <BackButton width="140px" onClick={goBack}>
          <i className="material-icons">first_page</i>
          Select cloud
        </BackButton>
        <Spacer x={1} inline />
        <Img src={aws} />
        <Text size={16}>Grant AWS permissions</Text>
      </Container>
      <Spacer y={1} />
      {renderContent()}
    </>
  );
};

export default CloudFormationForm;

const ImageDiv = styled.div`
  text-align: center;
`;

const StepChangeButtonsContainer = styled.div`
  display: flex;
`;

const Flex = styled.div`
  display: flex;
  ailgn-items: center;
  > i {
    margin-left: 10px;
    font-size: 16px;
    cursor: pointer;
  }
`;

const ButtonImg = styled.img`
  height: 14px;
  margin-right: 12px;
`;

const Img = styled.img`
  height: 18px;
  margin-right: 15px;
`;

const BackButton = styled.div`
  display: flex;
  align-items: center;
  justify-content: space-between;
  cursor: pointer;
  font-size: 13px;
  height: 35px;
  padding: 5px 13px;
  padding-right: 15px;
  border: 1px solid #ffffff55;
  border-radius: 100px;
  width: ${(props: { width: string }) => props.width};
  color: white;
  background: #ffffff11;

  :hover {
    background: #ffffff22;
  }

  > i {
    color: white;
    font-size: 16px;
    margin-right: 6px;
    margin-left: -2px;
  }
`;

const AWSButtonContainer = styled.div`
  display: flex;
  align-items: center;
`;
